package com.education.upload.service;

import com.education.upload.pojo.MultipartFileParam;
import com.education.upload.utils.QiniuUtil;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Client;
import com.qiniu.storage.ApiUploadV2CompleteUpload;
import com.qiniu.storage.ApiUploadV2ListParts;
import com.qiniu.storage.ApiUploadV2UploadPart;
import com.qiniu.storage.Configuration;
import com.qiniu.util.Auth;
import net.minidev.json.JSONUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: ly
 * @create: 2018-06-24 17:13
 **/
@Service
public class UploadService {

    private static final Logger logger = LoggerFactory.getLogger(UploadService.class);

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private QiniuUtil qiniuUtil;

    static final String PARTlIST_KEY = "partsInfo";

    /**
     * 获取uploadId
     *
     * @param multipartFileParam
     * @return
     */
    public Map<String, Object> getUploadId(MultipartFileParam multipartFileParam) throws Exception {
        logger.info("获取uploadId：" + multipartFileParam.toString());
        HashMap<String, Object> map = new HashMap<>();
        String fileName = multipartFileParam.getFilename();
        String[] split = fileName.split("\\.");
        String key = multipartFileParam.getIdentifier() + "." + split[split.length - 1];
        String uploadId = null;
        String obj = (String) redisTemplate.opsForValue().get(key);
        if (null != obj) {
            uploadId = obj;
        } else {
            uploadId = qiniuUtil.initiateMultipartUpload(key);
            redisTemplate.opsForValue().set(key, uploadId);
        }
        map.put("uploadId", uploadId);
        map.put("key", key);
        return map;
    }

    /**
     * 上传分片文件接口
     *
     * @param multipartFileParam
     * @return
     * @throws Exception
     */
    public Map<String, Object> uploadFile(MultipartFileParam multipartFileParam) throws Exception {
        logger.info("上传分片文件：" + multipartFileParam.toString());
        HashMap<String, Object> map = new HashMap<>();
        String key = null;
        String partListKey = null;
        try {
            MultipartFile file = multipartFileParam.getFile();
            if (file == null) {
                return null;
            }
            //获取文件名称
            String uploadId = multipartFileParam.getUploadId();
            String fileName = multipartFileParam.getFilename();
            String[] split = fileName.split("\\.");
            key = multipartFileParam.getIdentifier() + "." + split[split.length - 1];
            partListKey = PARTlIST_KEY + key;
            Map<String, Object> partMap = qiniuUtil.uploadPart(uploadId, key, multipartFileParam.getChunkNumber(), file.getBytes());
            redisTemplate.opsForList().rightPushAll(PARTlIST_KEY + key, partMap);
            map.put("uploadId", uploadId);
            map.put("key", key);
        } catch (Exception e) {
            logger.error("上传分片文件接口error：" + multipartFileParam.toString());
            logger.error("上传分片文件接口error", e);
            if (StringUtils.isNotBlank(key) && StringUtils.isNotBlank(partListKey)) {
                redisTemplate.delete(partListKey);
                redisTemplate.delete(key);
            }
            throw e;
        }
        return map;
    }

    /**
     * 上传完毕确认接口
     *
     * @param multipartFileParam
     * @return
     */
    public String uploadFileOk(MultipartFileParam multipartFileParam) throws Exception {
        logger.info("上传完毕确认接口：" + multipartFileParam.toString());
        String key = null;
        String partListKey = null;
        try {
            String uploadId = multipartFileParam.getUploadId();
            String fileName = multipartFileParam.getFilename();
            String[] split = fileName.split("\\.");
            key = multipartFileParam.getIdentifier() + "." + split[split.length - 1];
            String obj = (String) redisTemplate.opsForValue().get(key);
            partListKey = PARTlIST_KEY + key;
            List<Map<String, Object>> partsInfo = redisTemplate.opsForList().range(partListKey, 0, -1);
            if (null == obj) {
                return null;
            }
            if (null == partsInfo || partsInfo.size() == 0) {
                return null;
            }

            List<Map<String, Object>> partList = new ArrayList<>();
            List<Integer> partNumberList = new ArrayList<>();
            for (Map<String, Object> map : partsInfo) {
                Integer partNumber = Integer.valueOf(String.valueOf(map.get("partNumber")));
                partNumberList.add(partNumber);
            }
            List<Integer> compareList = partNumberList.stream().sorted().collect(Collectors.toList());
            for (Integer num : compareList) {
                for (Map<String, Object> map : partsInfo) {
                    Integer partNumber = Integer.valueOf(String.valueOf(map.get("partNumber")));
                    if (num.equals(partNumber)) {
                        partList.add(map);
                    }
                }
            }
            logger.info("上传七牛云：" + partList);
            boolean b = qiniuUtil.completeMultipartUpload(uploadId, key, fileName, partList);
            if (!b) {
                return null;
            }
        } catch (Exception e) {
            logger.error("上传七牛云error：" + key);
            logger.error("上传七牛云error", e);
            throw e;
        } finally {
            redisTemplate.delete(partListKey);
            redisTemplate.delete(key);
        }
        logger.info("上传七牛云成功：" + key);
        return key;
    }
}
